import numpy as np
from scipy import spatial
import matplotlib.pyplot as plt
from sko.GA import GA_TSP

def cal_order_sequence(order_sequence_list):
    # 将原始订单列表按照现在生成的订单顺序排好
    order_sequence_list_info = []
    for i in range(0, len(order_sequence_list)):
        # 读取当前列表中第i个，在原始订单列表中排第几
        select_order_index = order_sequence_list[i]
        temp_order = order_info[select_order_index]
        order_sequence_list_info.append(temp_order)
    # print(order_sequence_list_reorder)

    # 时间轴顺序列表
    product_time_order_list = []
    # 消耗时间顺序列表
    transform_cost_list = []
    for index, value in enumerate(order_sequence_list_info):
        time_end = 0
        if index != 0:
            transform_cost_time_string = order_sequence_list_info[index - 1][0] + '-' + value[0]
            temp_cost = 100000
            for i, v in enumerate(transform_cost):
                if (v['name'] == transform_cost_time_string):
                    temp_cost = v['cost']
                    break
                else:
                    temp_cost = 100000
            time_end = product_time_order_list[index - 1] + value[2] + temp_cost
        else:
            temp_cost = 0
            time_end = value[2]
        product_time_order_list.append(time_end)
        transform_cost_list.append(temp_cost)

    # 时间轴顺序信息
    product_time_axis_info_list = []
    for index, value in enumerate(order_sequence_list_info):
        temp = value.copy()
        temp.append(product_time_order_list[index])
        temp.append(transform_cost_list[index])
        product_time_axis_info_list.append(temp)
    # 返回列表里前四列是原始信息：类型，订单号，制造所需时间，交付时间，
    # 后两列为：制造完成的时间轴（开始时间为0），与前一个流程衔接所消耗时间
    return product_time_axis_info_list

# 计算适应度，求整体最小值
def cal_fitness(order_sequence_np):
    order_sequence_list = np.concatenate([order_sequence_np])
    # 获取整个时间轴
    product_time_axis_info_list = cal_order_sequence(order_sequence_list)
    # 计算衔接环节所消耗时间的适应度
    # 衔接环节所消耗时间的适应度
    transform_cost_value = 0
    for index, value in enumerate(product_time_axis_info_list):
        transform_cost_value = transform_cost_value + value[5]
    # 计算超时的适应度
    # 超时的适应度，如果有一个小于0，即没准时，则惩罚100分
    over_time_value = 100
    for index, value in enumerate(product_time_axis_info_list):
        # 计算超时的适应度
        temp_value = value[3] - value[4]
        if (temp_value < 0):
            over_time_value = 100
            break
        else:
            over_time_value = 0
    # 最后返回相加所得，整体是求最小值
    return transform_cost_value + over_time_value

if __name__ == '__main__':
    # 订单信息
    order_info = [
        ['A', '001', 3, 20],
        ['A', '002', 3, 50],
        ['B', '003', 4, 50],
        ['B', '004', 4, 20],
        ['B', '005', 4, 30],
        ['A', '006', 3, 50],
        ['B', '007', 4, 50],
        ['B', '008', 4, 50],
        ['A', '009', 3, 40],
        ['B', '010', 4, 50],
    ]
    order_num = len(order_info)
    transform_cost = [
        {'name': 'A-A', 'cost': 1},
        {'name': 'B-B', 'cost': 1},
        {'name': 'A-B', 'cost': 3},
        {'name': 'B-A', 'cost': 2},
    ]
    # 遗传算法规划问题
    ga_tsp = GA_TSP(func=cal_fitness, n_dim=order_num, size_pop=100, max_iter=500, prob_mut=1)
    best_order_sequence, best_fitness = ga_tsp.run()
    print(best_order_sequence, best_fitness)
    best_order_sequence_list = cal_order_sequence(best_order_sequence.tolist())
    print(best_order_sequence_list)

    # order_sequence_list = [0, 5, 6, 3, 4, 2, 7, 9, 1, 8]
    # order_sequence_list_info = cal_order_sequence(route)
    # print(order_sequence_list_info)
    # pass
